package com.hehe.Common;

import com.drew.imaging.ImageMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Upload_images {

    private static final List<String> SUPPORTED_FORMATS = Arrays.asList("jpg", "jpeg", "png", "gif", "bmp");

    // 整合后的方法：添加水印并压缩图片
    public static ArrayList<String> saveImagesWithWatermarkandCompress(String folderPath, MultipartFile[] files, int maxSizeKB, String watermarkText) {
        ArrayList<String> filePathList = new ArrayList<>();
        File folder = new File(folderPath);
        if (!folder.isDirectory()) {
            folder.mkdirs();
        }

        for (MultipartFile file : files) {
            try {
                File tempFile = File.createTempFile("temp", "." + getFileExtension(file));
                file.transferTo(tempFile);
                String savedFileName = CompressedImageWithWatermark(tempFile, folderPath, maxSizeKB, watermarkText);
                if (savedFileName != null) {
                    filePathList.add(savedFileName);
                }
            } catch (IOException e) {
                e.printStackTrace();
                return null; // 返回 null 表示出错
            }
        }
        return filePathList;
    }

    public static String CompressedImageWithWatermark(File inputFile, String outputDir, int maxSizeKB, String watermarkText) throws IOException {
        // 检查文件扩展名是否支持
        String fileExtension = getFileExtension(inputFile);
        if (!SUPPORTED_FORMATS.contains(fileExtension)) {
            throw new IllegalArgumentException("Unsupported file format: " + fileExtension);
        }

        String newName = UUID.randomUUID().toString() + "." + fileExtension;

        // 读取原始图像
        BufferedImage originalImage = ImageIO.read(inputFile);

        // 判断图片是否旋转
        Integer rotationDegrees = getRotationDegrees(inputFile.getPath());
        if (rotationDegrees != null) {
            originalImage = rotateImage(originalImage, rotationDegrees);  // 旋转图像
        }

        // 根据图像分辨率自适应计算水印大小
        int width = originalImage.getWidth();
        int height = originalImage.getHeight();
        int watermarkSize = calculateWatermarkSize(width, height);

        // 添加水印
        BufferedImage watermarkedImage = addTextWatermark(watermarkText, originalImage, watermarkSize);

        // 根据图片尺寸自适应缩放倍率
        int maxNumber = Math.max(watermarkedImage.getWidth(), watermarkedImage.getHeight());
        double scale = 1.0;
        if (maxNumber > 1400) {
            scale = Math.round(1400.0 / maxNumber * 100) / 100.0;  // 取 2 位小数 (大概是 0.17)
        }

        // 缩放图像
        BufferedImage scaledImage = Thumbnails.of(watermarkedImage)
                .scale(scale)
                .asBufferedImage();

        // 初始化压缩后的图像大小
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int quality = 100;
        Thumbnails.of(scaledImage)
                .scale(1) // 再次设置scale避免错误
                .outputFormat(fileExtension) // 指定输出格式
                .outputQuality(quality / 100.0)
                .toOutputStream(baos);

        int compressedSize = baos.toByteArray().length / 1024;

        // 循环减小质量直到压缩后的图像大小小于指定的大小
        while (compressedSize > maxSizeKB && quality > 0) {
            baos.reset();
            quality -= 5;
            Thumbnails.of(scaledImage)
                    .scale(1) // 再次设置scale避免错误
                    .outputFormat(fileExtension) // 指定输出格式
                    .outputQuality(quality / 100.0)
                    .toOutputStream(baos);
            compressedSize = baos.toByteArray().length / 1024;
        }

        // 保存压缩后的图像
        File outputFile = new File(outputDir, newName);
        Files.write(Paths.get(outputFile.toURI()), baos.toByteArray());

        System.out.println("Compressed image saved as: " + outputFile.getAbsolutePath());
        return newName;
    }

    // 旋转图像
    private static BufferedImage rotateImage(BufferedImage image, double angle) {
        double radians = Math.toRadians(angle);
        double sin = Math.abs(Math.sin(radians));
        double cos = Math.abs(Math.cos(radians));
        int w = image.getWidth();
        int h = image.getHeight();
        int newWidth = (int) Math.floor(w * cos + h * sin);
        int newHeight = (int) Math.floor(h * cos + w * sin);

        BufferedImage rotatedImage = new BufferedImage(newWidth, newHeight, image.getType());
        Graphics2D g2d = rotatedImage.createGraphics();

        AffineTransform at = new AffineTransform();
        at.translate((newWidth - w) / 2, (newHeight - h) / 2);
        at.rotate(radians, w / 2, h / 2);
        g2d.setTransform(at);
        g2d.drawRenderedImage(image, null);
        g2d.dispose();

        return rotatedImage;
    }

    // 添加水印
    private static BufferedImage addTextWatermark(String text, BufferedImage sourceImage, int size) {
        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

        // 设置透明度
        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
        g2d.setComposite(alphaChannel);

        // 设置水印字体和颜色
        g2d.setColor(Color.WHITE);
        g2d.setFont(new Font("Arial", Font.BOLD, size));

        // 开启抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        // 计算水印的位置
        int width = sourceImage.getWidth();
        int height = sourceImage.getHeight();
        int fontSize = g2d.getFont().getSize();
        int centerX = width / 2 - (text.length() * fontSize / 4);
        int centerY = height / 2;

        // 绘制水印
       // g2d.drawString(text, size, size); // 水印在左上角
        g2d.drawString(text, size, height - size); // 水印在左下角

        // 释放 Graphics2D 对象
        g2d.dispose();

        return sourceImage;
    }

    // 自适应图片分辨率的水印文字大小
    private static int calculateWatermarkSize(int width, int height) {
        int size = Math.min(width, height) / 15;  // 这里的 15 是一个系数，可以根据实际需求调整
        return Math.max(size, 20);  // 确保最小字体大小为 20
    }

    // 获取文件扩展名
    public static String getFileExtension(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
            return fileName.substring(dotIndex + 1).toLowerCase();
        }
        return ""; // 返回空字符串表示没有扩展名
    }

    // 获取文件扩展名
    public static String getFileExtension(File file) {
        String fileName = file.getName();
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex > 0 && dotIndex < fileName.length() - 1) {
            return fileName.substring(dotIndex + 1).toLowerCase();
        }
        return ""; // 返回空字符串表示没有扩展名
    }

    // 获取文件大小（单位：KB）
    public static long getFileSizeKB(File file) {
        return file.length() / 1024;
    }

    // 获取旋转角度
    public static Integer getRotationDegrees(String imgPath) {
        try {
            File imageFile = new File(imgPath);
            Metadata metadata = ImageMetadataReader.readMetadata(imageFile);
            for (Directory directory : metadata.getDirectories()) {
                for (Tag tag : directory.getTags()) {
                    if (tag.toString().contains("Exif IFD0] Orientation")) {
                        String regex = "Rotate (\\d+) CW";
                        Pattern pattern = Pattern.compile(regex);
                        Matcher matcher = pattern.matcher(tag.toString());
                        if (matcher.find()) {
                            String rotationDegrees = matcher.group(1);
                            return Integer.valueOf(rotationDegrees);
                        }
                    }
                }
                if (directory.hasErrors()) {
                    for (String error : directory.getErrors()) {
                        System.err.println("ERROR: " + error);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
